package ogmios.core;
/**
 * Ogmios  - A Java IDE<br/>
 * This is the GUI, and includes most of the basic IDE services.
 * @author Mike Capasso, Oliver Kubik, Zachary Littrell
 * @version Pluto 1.1
 */
import javax.swing.plaf.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.text.rtf.*;
import javax.swing.undo.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.table.*;
import java.util.regex.*;
import java.util.List;
import java.security.*;
import ogmios.components.*;
import ogmios.components.munches.*;
import ogmios.dialogs.*;
import ogmios.processes.*;
public class Ogmios extends JFrame
{

  /**The instance variable carrying Ogmios's GUI and functions*/
  public static Ogmios ogmiosGUI;
  public static final String OGMIOS_TITLE = "Ogmios";
  public static final double OGMIOS_VERSION = 1.05;
  public static final String OGMIOS_PSEUDONYM = "Charon";


//Utilities
  public static String jAddress = "";
  public static String javaPackage = "";
  public static String sourcePath = "";
  public static String classPath = "";
  public static String[] javaArgs = ListDialog.emptyStringArray;
  public static String[] javacArgs = ListDialog.emptyStringArray;
  public static String[] appArgs = ListDialog.emptyStringArray;
  public static String compilerDirectory = "";
  public static String executionerDirectory = "";
  public static String appletViewerDirectory = "";
  public static int MAX_UNDO_LEVEL = 1024;


  public Munchkin munchkin;
  public ArchiveBuilder archiveBuilder;
  public TemplateManager javaTemplateManager;
  public static FindAndReplaceDialog findAndReplaceDialog;
  public Process currentProcess;
  public static ClassLoader munchLoader;
  public OutputWriter processWriter;
  public Thread inThread;
  public Thread errThread;
  public Thread waitThread;
  public OgmiosGUIUpdater updateGUI;
  public Runnable clearGUI;
  public Runnable stopButtonDisabler;
  public Runnable runThread;

  public static ItemListener setReactionsSettings;
  public static ItemListener setRadioSettings;

  public static Set<String> munchBlacklist;
  public static Map<String, String> settingsMap;
  public final Map<String, Extension> extensions = new HashMap<String, Extension>();

  public JSplitPane treeSplit, logsSplit;
  public JScrollPane treeScroll, codeScroll, outScroll, errScroll, inScroll;
  
  public SplitTabPane codeTab;
  public JTabbedPane errTab;

  public JTree tree;
  public DefaultTreeModel treeModel;
  public DefaultMutableTreeNode treeRoot;

  public OgmiosTextPane code;


  public Runnable scrollCode;
  public JEditorPane inLog;
  public UndoManager inLogUndo;
  public JTextArea outLog;

  public DefaultListModel errLogList;
  public JList errLog;

  public Terminal terminal;

  public JMenuBar menu;
   public JMenu fileMenu;
    public JMenuItem openFile, saveFile, saveAsFile, renameFile, closeMultipleFiles, closeFile,  exitOgmios;
   public JMenu newMenu;
    public JMenuItem newFile, blankDocument, templateManager;
   public JMenu printMenu;
    public JMenuItem printFile, printSelectedText;
   public JMenu javaMenu;
    public JMenuItem compileAndRun, compile, run, runInAppletViewer;
   public JMenu settingsMenu;
    public JMenu commandLineArgs;
     public JMenuItem compilerArgs,  executionerArgs, packageArg, sourcePathArg, classPathArg, postArgs;
     public JMenu workingDirectories;
      public JMenuItem compilerDirectoryArg, executionerDirectoryArg, appletViewerDirectoryArg;
    public JMenu locateJDK;
     public JMenuItem autoLocateJDK, locateJDKManually;
    public JMenu tabsSettings;
     public JCheckBoxMenuItem splitCodeTab;
    public JMenu terminalSettings;
    public JMenu errLogRegex;
     public RegexRadioButtonMenuItem colonFlankedRegex, oneColonRegex;
     public ButtonGroup errLogRegexGroup;
    public JMenu reactionsSettings;
     public JCheckBoxMenuItem runInOutputTab, printInputOnOutput, showNewErrors, clearOutput, clearError;
    public JMenu lookAndFeelsSettings;
    public JMenuItem saveSettingsManually;
   public JMenu toolsMenu;
    public JMenuItem gotoLine, insertAppletTag, publishInHTML, launchMacroScripter;
    public JMenu buildArchive;
     public JMenuItem buildZip, buildJar;
   public JMenu aboutMenu;
    public JMenuItem help, about;
   public JMenu munchMenu;
    public JMenu extensionMenu;
     public JMenu runExtension;
     public JMenuItem buildExtension;
    public JMenu commandMenu;
     public JMenuItem browseCommands, buildCommand;
   public JButton stopButton;
 
  public OgmiosNode activeNode;

  public JPopupMenu nodePopupMenu;
  public JMenuItem openNode, closeNode, getInfoFromNode;
  public JPopupMenu errLogPopupMenu;
  public JMenuItem copyErrLogLine, copyErrLog;


  private List<Component> processWatchers = new ArrayList<Component>();

  public UndoManager undo;


  /**
   * The main method
   * @param	args		The command line arguments.
   *				Filenames in the command line arguments are opened initially.
   */
  public static void main(String[] args) throws Throwable
  {
   Toolkit toolkit = Toolkit.getDefaultToolkit();
   Dimension screenSize = toolkit.getScreenSize();
//Default to System look and feel (on NON-Macs,
//it would default to the Swing LAF)
    settingsMap = new HashMap<String, String>();
    try
    {
      File settingsFile;
      if ((settingsFile = new File("settings.ogs")).exists())
      {
        BufferedReader r = new BufferedReader(new FileReader(settingsFile));
        String line;
        while ((line = r.readLine()) != null)
        {
          int i;
          if ((i = line.indexOf(":")) > 0 && i < line.length() - 1)
          {
            settingsMap.put(line.substring(0, i), line.substring(i + 1));
          }
        }
        r.close();

      }
    }
    catch (Throwable ex)
    {
      OgmiosUtilities.showErrorBox(null, ex, "Settings:Reading Error");
    }
    String laf = settingsMap.get("ogmiosLAF");
    if (laf != null)
    {
      try
      {
        UIManager.setLookAndFeel(laf);
      }
      catch (Throwable ex)
      {
        try
        {
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
          settingsMap.remove("ogmiosLAF");
        }
        catch (Throwable e)
        {

        }
      }

    }
    else
    {

      try
      {

        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        System.setProperty("apple.laf.useScreenMenuBar", "false");



      }
      catch (Throwable ex)
      {

      }

    }



    ogmiosGUI = new Ogmios();
    File extensionFolder = new File("extensions");
    if (extensionFolder.exists())
    {
      try
      {
        ClassLoader loader =  Ogmios.ogmiosGUI.getMunchLoader();//Ogmios.class.getClassLoader();//new URLClassLoader(new URL[] {extensionFolder.toURI().toURL()});
        for (File extensionFile : extensionFolder.listFiles(new OgmiosFileFilter(".class", "Class Files")))
        {
          //exclude inner classes
          if (extensionFile.getName().lastIndexOf('$') == -1)
            try
            {
              Class loadedClass = loader.loadClass("extensions." + OgmiosUtilities.unextendedFileName(extensionFile.getName()));
              Object newExtension = loadedClass.newInstance();
              if (newExtension instanceof Extension)
              {
                Extension extension = (Extension)newExtension;
                extension.initialize();
                ogmiosGUI.extensions.put(loadedClass.getSimpleName(), extension);
              }
            }
            catch (Throwable ex)
            {
              OgmiosUtilities.showErrorBox(null, ex, "Extension:Loading Error");
            }
        }
      }
      catch (Throwable e)
      {
        OgmiosUtilities.showErrorBox(null, e, "Extension:Classpath Error");
      }
    }
    ogmiosGUI.pack();
    String val;

    if ((val = settingsMap.get("height")) != null)
    {
      int height;
      height  = OgmiosUtilities.tryParse(val);
      if (OgmiosUtilities.success)
        if ((val = settingsMap.get("width")) != null)
        {
          int width;
          width = OgmiosUtilities.tryParse(val);
          if (OgmiosUtilities.success)
            ogmiosGUI.setSize(width, height);
        }
    }
    if ((val = settingsMap.get("state")) != null && val.equals("m"))
      ogmiosGUI.setExtendedState(Frame.MAXIMIZED_BOTH);
    ogmiosGUI.addComponentListener(
      new ComponentAdapter()
    {
      public void componentResized(ComponentEvent e)
      {

        if (ogmiosGUI.getExtendedState() == Frame.MAXIMIZED_BOTH)
        {
          settingsMap.put("state", "m");
        }
        else
        {
          settingsMap.put("state", "n");
          settingsMap.put("width", Integer.toString(ogmiosGUI.getWidth()));
          settingsMap.put("height", Integer.toString(ogmiosGUI.getHeight()));
        }
      }
    }
    );


   

    boolean b;
    val = settingsMap.get(ogmiosGUI.splitCodeTab.getText());
    if (val!= null)
    {
     b = OgmiosUtilities.tryParseBooleanNumber(val);
     if (OgmiosUtilities.success)
      ogmiosGUI.splitCodeTab.setState(b);
    }
    ogmiosGUI.splitCodeTab.addItemListener(setReactionsSettings);
 
 

    for (Component com : ogmiosGUI.reactionsSettings.getMenuComponents())
    {
      JCheckBoxMenuItem chk = (JCheckBoxMenuItem)com;
      if ((val = settingsMap.get(chk.getText())) != null)
      {
        b = OgmiosUtilities.tryParseBooleanNumber(val);
        if (OgmiosUtilities.success)
          chk.setState(b);
      }
      chk.addItemListener(setReactionsSettings);

    }
    if ((val = settingsMap.get(ogmiosGUI.errLogRegex.getText())) != null)
    {
      int n = OgmiosUtilities.tryParse(val);
      if (OgmiosUtilities.success && n >= 0 && n <= ogmiosGUI.errLogRegex.getMenuComponentCount() - 1)
        ogmiosGUI.errLogRegexGroup.setSelected(((JRadioButtonMenuItem)ogmiosGUI.errLogRegex.getMenuComponent(n)).getModel(), true);
      else if (ogmiosGUI.errLogRegex.getMenuComponentCount() > 0)
        ogmiosGUI.errLogRegexGroup.setSelected(((JRadioButtonMenuItem)ogmiosGUI.errLogRegex.getMenuComponent(0)).getModel(), true);
    }
    else if (ogmiosGUI.errLogRegex.getMenuComponentCount() > 0)
      ogmiosGUI.errLogRegexGroup.setSelected(((JRadioButtonMenuItem)ogmiosGUI.errLogRegex.getMenuComponent(0)).getModel(), true);

    for (Component com : ogmiosGUI.errLogRegex.getMenuComponents())
    {
      ((JRadioButtonMenuItem)com).addItemListener(setRadioSettings);
    }
   
    if (ogmiosGUI.codeTab.isSplit())
    {
     JSplitPane split;
     ogmiosGUI.setVisible(true);
     ogmiosGUI.invalidate();
     ogmiosGUI.validate(); 
     (split = ogmiosGUI.codeTab.getSplitPane()).setDividerLocation(0.5D);
     split.invalidate();
     split.validate();
   }
   else
   {
     ogmiosGUI.setVisible(true);
   }
 
//this will typically be 0, but this is in anticipation of potential
//extensions that plop files in Ogmios.
    int childCount = ogmiosGUI.treeRoot.getChildCount();
    for (int i = 0; i < args.length; i++)
    {
      File javaFile = new File(args[i]);
      if (javaFile.exists() && javaFile.isFile())
      {
        try
        {
          /*OgmiosNode node;
          ogmiosGUI.treeModel.insertNodeInto(node = new OgmiosNode(javaFile.getCanonicalPath()), ogmiosGUI.treeRoot, `ogmiosGUI.treeRoot.getChildCount());
          FileInputStream input = new FileInputStream(javaFile)png;
          ogmiosGUI.code.getEditorKit().read(input, node.document, 0);
          input.close();

          node.document.putProperty(DefaultEditorKit.EndOfLineStringProperty, OgmiosUtilities.newLine);
          node.setDefaultDocumentListener(ogmiosGUI.createDefaultDocumentListener(node),true);
          node.setUndo(true);*/
          ogmiosGUI.treeModel.insertNodeInto(ogmiosGUI.createNodeFromFile(javaFile), ogmiosGUI.treeRoot, ogmiosGUI.treeRoot.getChildCount());
        }
        catch (Throwable ex)
        {
          OgmiosUtilities.showErrorBox(null, ex, "IO:Reading Error");
        }
      }
    }
    if ((ogmiosGUI.treeRoot.getChildCount() - childCount) > 0 )
    {
      ogmiosGUI.openDocument((OgmiosNode)ogmiosGUI.treeRoot.getChildAt(childCount));
    }

  }

  public Ogmios()
  {

    Toolkit kit = Toolkit.getDefaultToolkit();
    Image img;
    try
    {
      URL url = ClassLoader.getSystemResource("ogmiosico.png");
      img = kit.createImage(url);
      setIconImage(img);
    }
    catch (Throwable ex)
    {
      img = getIconImage();
    }

    setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    setTitle(OGMIOS_TITLE);
   // codeTab = new JTabbedPane();
    codeTab = new SplitTabPane();
    OgmiosUtilities.tabbable(codeTab.getTabbedPane());
    {
      JSplitPane split = codeTab.getSplitPane();
     // split.setDividerLocation(0.5);
      split.setResizeWeight(0.5);
     }
    errTab = OgmiosUtilities.tabbable(new JTabbedPane());

    updateGUI = new OgmiosGUIUpdater();
    clearGUI =
      new Runnable()
    {
      public void run()
      {
        stopButton.setVisible(true);

        if (clearError.getState())
          errLogList.clear();

        if (clearOutput.getState())
          outLog.setText("");

        updateGUI.enable = false;
        updateGUI.run();
      }
    };
    stopButtonDisabler =
      new Runnable()
    {
      public void run()
      {
        stopButton.setVisible(false);
      }
    };

    runThread = new Runnable()
    {
      public void run()
      {

        if (currentProcess != null && errLogList.getSize() == 0 && new File(activeNode.directory + File.separator + activeNode.nameWithoutExtension() + ".class").exists())
        {
          if (runInOutputTab.getState())
            codeTab.setSelectedComponent(false);
            //codeTab.setSelectedComponent(false);
          String[] args;

          String path = executionerDirectory.length() == 0 ?
                                OgmiosUtilities.getBasePackagePath(activeNode.directory + File.separator,javaPackage)  : executionerDirectory;
          args = new String[4 + javaArgs.length + appArgs.length];
          args[0] = jAddress + File.separator + "java";
          args[1] = "-cp";
          args[2] = path + File.pathSeparator + classPath;
          int i;
          int index = 2;

          for (i = 0; i < javaArgs.length; i++)
          {
            args[++index] = javaArgs[i];

          }
          args[++index] = javaPackage + activeNode.nameWithoutExtension() ;
          for (i = 0; i < appArgs.length; i++)
          {
            args[++index] = appArgs[i];
          }


          runProcess(args, null, new File(path));
        }
      }
    } ;
   

    findAndReplaceDialog = new FindAndReplaceDialog();
    tree = new JTree( treeModel = new DefaultTreeModel ( treeRoot = new DefaultMutableTreeNode("Documents")));
    errLogList = new DefaultListModel();
    menu = new JMenuBar();
    code = new OgmiosTextPane();
    code.setName("Code");

    undo = new UndoManager();
    undo.setLimit(MAX_UNDO_LEVEL);
    scrollCode =
      new Runnable()
    {

      public void run()
      {
        codeScroll.getVerticalScrollBar().setValue(activeNode.verticalPosition);
        codeScroll.getHorizontalScrollBar().setValue(activeNode.horizontalPosition);
      }
    };
    outLog = new JTextArea();
    outLog.setName("Output");
    errLog = new JList(errLogList);
    errLog.setName("Error Log");
    inLog = new JEditorPane();
    terminal = new Terminal();
    terminal.setName("Terminal");
    int mask = kit.getMenuShortcutKeyMask();

    fileMenu = new JMenu("File");
     fileMenu.setMnemonic(KeyEvent.VK_F);
     fileMenu.add(newMenu = new JMenu("New"));
      newMenu.add(newFile = new JMenuItem("New File"));
      newFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, mask));
      newMenu.add(blankDocument = new JMenuItem("Blank Document"));
      newMenu.add(templateManager = new JMenuItem("Show Template Manager"));
      templateManager.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, mask));
     fileMenu.add(openFile = new JMenuItem("Open"));
      openFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, mask));
     fileMenu.add(saveFile = new JMenuItem("Save"));
      saveFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, mask));
     fileMenu.add(saveAsFile = new JMenuItem("Save As"));
     fileMenu.add(renameFile = new JMenuItem("Rename"));
      renameFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, mask));
     fileMenu.add(printMenu = new JMenu("Print"));
      printMenu.add(printFile = new JMenuItem("Print Document"));
       printFile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, mask));
      printMenu.add(printSelectedText = new JMenuItem("Print Selected Text"));
     fileMenu.add(closeFile = new JMenuItem("Close Document"));
     fileMenu.add(closeMultipleFiles = new JMenuItem("Close Multiple Documents"));
     fileMenu.add(exitOgmios = new JMenuItem("Exit"));
    javaMenu = new JMenu("Java");
     javaMenu.setMnemonic(KeyEvent.VK_J);
     javaMenu.add(compileAndRun = new JMenuItem("Compile And Run"));
      compileAndRun.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0));
     javaMenu.add(compile = new JMenuItem("Compile"));
      compile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0));
     javaMenu.add(run = new JMenuItem("Run"));
      run.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F9, 0));
     javaMenu.add(runInAppletViewer = new JMenuItem("Run in Applet Viewer"));
      runInAppletViewer.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
    settingsMenu = new JMenu("Settings");
     settingsMenu.setMnemonic(KeyEvent.VK_S);
     settingsMenu.add(commandLineArgs = new JMenu("Command Line Args"));
      commandLineArgs.add(compilerArgs = new JMenuItem("Compiler"));
      commandLineArgs.add(executionerArgs = new JMenuItem("Executioner"));
      commandLineArgs.add(postArgs = new JMenuItem("My Application"));
      commandLineArgs.add(packageArg = new JMenuItem("Package"));
      commandLineArgs.add(sourcePathArg = new JMenuItem("Sourcepath"));
      commandLineArgs.add(classPathArg = new JMenuItem("Classpath"));
      commandLineArgs.add(workingDirectories = new JMenu("Working Directories"));
       workingDirectories.add(compilerDirectoryArg = new JMenuItem("Compiler Working Directory"));
       workingDirectories.add(executionerDirectoryArg  = new JMenuItem("Executioner Working Directory"));
       workingDirectories.add(appletViewerDirectoryArg = new JMenuItem("Applet Viewer Directory"));
     settingsMenu.add(locateJDK = new JMenu("Locate JDK Bin"));
      locateJDK.add(autoLocateJDK = new JMenuItem("Auto-Locate"));
      locateJDK.add(locateJDKManually = new JMenuItem("Locate Manually"));
     settingsMenu.add(tabsSettings = new JMenu("Tabs"));
      tabsSettings.add(splitCodeTab = new JCheckBoxMenuItem("Split Code Tab", false));
     settingsMenu.add(makeAndSetupComponentSettings(code, "TextPane"));
     settingsMenu.add(makeAndSetupComponentSettings(outLog, "TextArea"));
     JMenu errSettings = makeAndSetupComponentSettings(errLog, "List");
     settingsMenu.add(errSettings);
      errSettings.add(errLogRegex = new JMenu("Error Log Regex"));
       errLogRegex.add(colonFlankedRegex = new RegexRadioButtonMenuItem(":(\\d+)", 1));
      errLogRegex.add(oneColonRegex = new RegexRadioButtonMenuItem(":(\\d+):", 1));
       errLogRegexGroup = new ButtonGroup();
       errLogRegexGroup.add(colonFlankedRegex);
       errLogRegexGroup.add(oneColonRegex);
     settingsMenu.add(terminalSettings = new JMenu("Terminal Settings"));
       terminalSettings.add(makeAndSetupComponentSettings(terminal.getTerminalOutput(), "TextArea"));
       terminalSettings.add(makeAndSetupComponentSettings(terminal.getTerminalInput(), "TextArea"));
       terminalSettings.add(makeAndSetupComponentSettings(terminal.getTerminalCurrentWorkingDirectoryLabel(), "Label"));
     settingsMenu.add(reactionsSettings = new JMenu("Reactions"));
      reactionsSettings.add(runInOutputTab = new JCheckBoxMenuItem("Run in Output Tab", true));
      reactionsSettings.add(printInputOnOutput = new JCheckBoxMenuItem("Print Input On Output", true));
      reactionsSettings.add(showNewErrors = new JCheckBoxMenuItem("Show New Errors", true));
      reactionsSettings.add(clearOutput = new JCheckBoxMenuItem("Refresh Output", true));
      reactionsSettings.add(clearError = new JCheckBoxMenuItem("Refresh Error Log", true));
     settingsMenu.add(lookAndFeelsSettings = new JMenu("Swing Look & Feels"));
     settingsMenu.add(saveSettingsManually = new JMenuItem("Save Settings"));
    toolsMenu = new JMenu("Tools");
     toolsMenu.setMnemonic(KeyEvent.VK_T);
     toolsMenu.add(gotoLine = new JMenuItem("Goto Line"));
     toolsMenu.add(buildArchive = new JMenu("Build Archive"));
      buildArchive.add(buildZip = new JMenuItem("Build Zip"));
      buildArchive.add(buildJar = new JMenuItem("Build Jar"));
     toolsMenu.add(insertAppletTag = new JMenuItem("Insert Applet Tag"));
     toolsMenu.add(publishInHTML = new JMenuItem("Publish in HTML"));
     toolsMenu.add(launchMacroScripter = new JMenuItem("Launch New Macro Scripter"));
    aboutMenu = new JMenu("About");
     aboutMenu.setMnemonic(KeyEvent.VK_A);
     aboutMenu.add(help = new JMenuItem("Help"));
     aboutMenu.add(about = new JMenuItem("About"));
    munchMenu = new JMenu("Plugins");
     munchMenu.setMnemonic(KeyEvent.VK_P);
     munchMenu.add(extensionMenu = new JMenu("Extensions"));
      extensionMenu.add(runExtension = new JMenu("Run Extension"));
      extensionMenu.add(buildExtension = new JMenuItem("Build Extension"));
     munchMenu.add(commandMenu = new JMenu("Commands"));
      commandMenu.add(browseCommands = new JMenuItem("Browse Commands"));
      commandMenu.add(buildCommand = new JMenuItem("Build Command"));
    stopButton = new JButton("Stop");
    nodePopupMenu = new JPopupMenu("Ogmios Tree");
    nodePopupMenu.add(openNode = new JMenuItem());
    nodePopupMenu.add(closeNode = new JMenuItem());
    nodePopupMenu.add(getInfoFromNode = new JMenuItem());
    errLogPopupMenu = new JPopupMenu("Error Log");
    errLogPopupMenu.add(copyErrLogLine = new JMenuItem("Copy Selected Lines"));
    errLogPopupMenu.add(copyErrLog = new JMenuItem("Copy Error Log"));


    treeScroll = new JScrollPane(tree);
    codeScroll = new JScrollPane(code);
    outScroll = new JScrollPane(outLog);
    errScroll = new JScrollPane(errLog);
    inScroll = new JScrollPane(inLog);



   codeTab.setLeftComponent(codeScroll, "Code");
   codeTab.setRightComponent(outScroll, "Output");
   {
      JTabbedPane tabbedPane = codeTab.getTabbedPane();
      tabbedPane.setMnemonicAt(0, KeyEvent.VK_C);
      tabbedPane.setMnemonicAt(1, KeyEvent.VK_O);
    }
    errTab.add(errScroll, "Error Log");
    errTab.setMnemonicAt(0, KeyEvent.VK_E);
    errTab.add(inScroll, "Input");
    errTab.setMnemonicAt(1, KeyEvent.VK_I);
    errTab.add(terminal, "Terminal");
    errTab.setMnemonicAt(2, KeyEvent.VK_T);

    menu.add(fileMenu);
    menu.add(javaMenu);
    menu.add(settingsMenu);
    menu.add(toolsMenu);
    menu.add(aboutMenu);
    menu.add(munchMenu);
    menu.add(stopButton);
    {
    Dimension size = menu.getPreferredSize();
    size.height = stopButton.getPreferredSize().height;
    menu.setPreferredSize(size);
    }
    logsSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, codeTab, errTab);
    treeSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeScroll, logsSplit);


    setJMenuBar(menu);
    getContentPane().add(treeSplit, BorderLayout.CENTER);

//Adjustments and Settings for the GUI
    logsSplit.setResizeWeight(1);
    stopButton.setVisible(false);
    stopButton.setForeground(Color.red);
//code.setOpaque(false);

    code.getDocument().addUndoableEditListener(undo);
    outLog.setEditable(false);
    tree.getSelectionModel().setSelectionMode(javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setFont(tree.getFont().deriveFont(Font.BOLD));


//listeners and adapters

    addWindowListener(
      new WindowAdapter()
    {
      public void windowClosing(WindowEvent e)
      {
        System.exit(0);
      }
    }
    );

    System.setSecurityManager(
      new SecurityManager()
    {
      public void checkPermission(Permission slip)
      {
        if (slip.getName().contains("exitVM"))
        {
          if (stopButton.isVisible())
          {
            try
            {
              currentProcess.destroy();
            }
            catch (Throwable ex)
            {
            }
          }
          if (!promptUntitledWorkSave())
          {
            throw new SecurityException();
          }
          else
          {
            MultiSaveDialog savePrompt = new MultiSaveDialog();
            for (Enumeration children = treeRoot.preorderEnumeration(); children.hasMoreElements();)
            {
              TreeNode node = (TreeNode) children.nextElement();
              if (node instanceof OgmiosNode)
              {
                OgmiosNode ogmiosNode = (OgmiosNode) node;

                 savePrompt.addSavable(ogmiosNode);
              }
            }
               if (!savePrompt.canClose(Ogmios.ogmiosGUI))
                 throw new SecurityException();
          }
          saveSettings();

        }
    
     }
    }
    );

    tree.setCellRenderer(
      new DefaultTreeCellRenderer()
    {
      public Component getTreeCellRendererComponent(JTree tree, Object val,
          boolean selected,
          boolean expanded, boolean leaf,
          int row, boolean hasFocus)
      {
        /*setIcon(leaf ?
        	val instanceof OgmiosNode ?
        		getLeafIcon() :
        		getClosedIcon() :
        	expanded ? getOpenIcon() :
        	getClosedIcon()
        	);*/

        if (val instanceof OgmiosNode)
        {
          setIcon(getLeafIcon());
          setText(((OgmiosNode)val).saveNeeded ? "*" + val.toString() : val.toString());
        }
        else
        {
          setIcon(leaf ? getClosedIcon() : expanded ? getOpenIcon() : getClosedIcon());
          setText(val.toString());
        }
        this.selected = selected;
        this.hasFocus = hasFocus;
        setHorizontalAlignment(LEFT);
        setOpaque(false);
        setVerticalAlignment(CENTER);
        setEnabled(true);
        super.setFont(UIManager.getFont("Tree.font"));

        if (selected)
        {
          super.setBackground(getBackgroundSelectionColor());
          setForeground(getTextSelectionColor());

          if (hasFocus)
            setBorderSelectionColor(UIManager.getLookAndFeelDefaults().getColor("Tree.selectionBorderColor"));
          else
            setBorderSelectionColor(null);
        }
        else
        {
          setBackgroundNonSelectionColor(val == activeNode ? Color.green : Color.white);
          super.setBackground(getBackgroundNonSelectionColor());
          setForeground(getTextNonSelectionColor());
          setBorderSelectionColor(null);
        }

        return this;
      }
      public void updateUI()
      {
        setLeafIcon(UIManager.getIcon("Tree.leafIcon"));
        setClosedIcon(UIManager.getIcon("Tree.closedIcon"));
        setOpenIcon(UIManager.getIcon("Tree.openIcon"));
        setTextSelectionColor(UIManager.getColor("Tree.selectionForeground"));
        setTextNonSelectionColor(UIManager.getColor("Tree.textForeground"));
        setBackgroundSelectionColor(UIManager.getColor("Tree.selectionBackground"));
        setBackgroundNonSelectionColor(UIManager.getColor("Tree.textBackground"));
        setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor"));
        super.updateUI();
        treeModel.reload();
      }
    }
    );

    tree.addMouseListener(
      new MouseAdapter()
    {
      public void mouseClicked(MouseEvent e)
      {
        if (e.getClickCount() == 2)
        {
          TreePath obj = tree.getPathForLocation(e.getX(), e.getY());
          if (obj != null)
          {
            DefaultMutableTreeNode o = (DefaultMutableTreeNode)obj.getLastPathComponent();
            if (o instanceof OgmiosNode)
            {
              if (promptUntitledWorkSave())
                openDocument((OgmiosNode)o);
            }
          }
        }
      }
      //both pressed and released are set
      //as I've read that not all platforms
      //associate their popup triggers in the same
      //place
      public void mousePressed(MouseEvent e)
      {
        if (e.isPopupTrigger())
        {
          TreePath obj = tree.getPathForLocation(e.getX(), e.getY());
          if (obj != null)
          {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)obj.getLastPathComponent();
            if (node instanceof OgmiosNode)
            {
              String s = (node.toString());
              openNode.setText("Open " + s);
              closeNode.setText("Close " + s);
              getInfoFromNode.setText("Get Info About " + s);
              tree.setSelectionPath(obj);
              nodePopupMenu.show(tree, e.getX(), e.getY());
            }
          }
        }
      }
      public void mouseReleased(MouseEvent e)
      {
        if (e.isPopupTrigger())
        {
          TreePath obj = tree.getPathForLocation(e.getX(), e.getY());
          if (obj != null)
          {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)obj.getLastPathComponent();
            if (node instanceof OgmiosNode)
            {
              String s = (node.toString());
              openNode.setText("Open " + s);
              closeNode.setText("Close " + s);
              getInfoFromNode.setText("Get Info About " + s);
              tree.setSelectionPath(obj);
              nodePopupMenu.show(tree, e.getX(), e.getY());
            }
          }
        }
      }

    }
    );

    tree.addKeyListener(
      new KeyAdapter()
    {
      public void keyPressed(KeyEvent e)
      {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
        {
          TreePath path = tree.getSelectionPath();
          if (path != null)
          {
            DefaultMutableTreeNode n = (DefaultMutableTreeNode)path.getLastPathComponent();
            if (n instanceof OgmiosNode)
            {

              if (promptUntitledWorkSave())
                openDocument((OgmiosNode) n);
            }
            else if (tree.isExpanded(path))
              tree.collapsePath(path);
            else
              tree.scrollPathToVisible(path);
          }
        }
      }
    }
    );

    openNode.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {


        if (promptUntitledWorkSave() == false)
          return;


        openDocument((OgmiosNode)tree.getSelectionPath().getLastPathComponent());
      }
    }
    );

    closeNode.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        closeDocument((OgmiosNode)tree.getSelectionPath().getLastPathComponent());
      }
    }
    );
    getInfoFromNode.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        OgmiosNode node = (OgmiosNode)tree.getSelectionPath().getLastPathComponent();
        JOptionPane.showMessageDialog(Ogmios.this, OgmiosUtilities.getTextBox(
                                        "Name:" + node.name + "\nDirectory:" + node.directory + "\nLine Count:" + node.document.getDefaultRootElement().getElementCount()), "Info", JOptionPane.INFORMATION_MESSAGE);
      }
    }
    );

    inLog.addKeyListener(
      new KeyAdapter()
    {
      public void keyPressed(KeyEvent e)
      {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
        {
          e.consume();
          if (stopButton.isVisible())
          {
            inLog.setText(inLog.getText() + "\n");
            processWriter.write();
          }
          inLog.setText("");
        }
      }
    }
    );

    errLog.addMouseListener(
      new MouseAdapter()
    {
      public void mouseClicked(MouseEvent e)
      {
        if (errLogList.getSize() > 0 && activeNode != null &&  e.getClickCount() == 2)
        {
          for (Enumeration en = errLogRegexGroup.getElements(); en.hasMoreElements();)
          {
            RegexRadioButtonMenuItem b = (RegexRadioButtonMenuItem) en.nextElement();
            if (b.getModel() == errLogRegexGroup.getSelection())
            {
              String s;
              Matcher match = b.pattern.matcher(s = errLog.getSelectedValue().toString());
              if (match.find())
              {

                int line = OgmiosUtilities.tryParse(match.group(b.group));
                if (OgmiosUtilities.success)
                {
                  if (OgmiosUtilities.gotoLine(code, line))
                    codeTab.setSelectedComponent(true);    
                   
                }

              }
              return;
            }

          }
        }
      }
      public void mousePressed(MouseEvent e)
      {
        if (e.isPopupTrigger() && errLogList.getSize() > 0)
        {
          copyErrLogLine.setVisible(!errLog.isSelectionEmpty());
          errLogPopupMenu.show(errLog, e.getX(), e.getY());
        }
      }
      public void mouseReleased(MouseEvent e)
      {
        if (e.isPopupTrigger() && errLogList.getSize() > 0)
        {
          copyErrLogLine.setVisible(!errLog.isSelectionEmpty());
          errLogPopupMenu.show(errLog, e.getX(), e.getY());

        }
      }
    }
    );

    errLog.addKeyListener(
      new KeyAdapter()
    {
      public void keyPressed(KeyEvent e)
      {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
        {
          Object value =   errLog.getSelectedValue();
          if (errLogList.getSize() > 0 && activeNode != null && value != null)
          {
            for (Enumeration en = errLogRegexGroup.getElements(); en.hasMoreElements();)
            {
              RegexRadioButtonMenuItem b = (RegexRadioButtonMenuItem) en.nextElement();
              if (b.getModel() == errLogRegexGroup.getSelection())
              {
                String s;
                Matcher match = b.pattern.matcher(s = value.toString());
                if (match.find())
                {

                  int line = OgmiosUtilities.tryParse(match.group(b.group));
                  if (OgmiosUtilities.success)
                  {
                    if (OgmiosUtilities.gotoLine(code, line))
                    {
                      codeTab.setSelectedComponent(true);
                    }
                  }

                }
                return;
              }

            }
          }
        }
      }
    }
    );

    copyErrLog.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (errLogList.getSize() > 0)
        {
          StringBuilder sb = new StringBuilder();
          Enumeration el = errLogList.elements();
          while (true)
          {
            sb.append(el.nextElement());
            if (el.hasMoreElements())
              sb.append("\n");
            else
              break;
          }
          Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(sb.toString()), null);
        }
      }
    }
    );
    copyErrLogLine.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        Object[] values = errLog.getSelectedValues();
        StringBuilder sb = new StringBuilder();
        int i;
        for (i = 0; i < values.length - 1; i++)
          sb.append(values[i] + "\n");
        sb.append(values[i]);
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(sb.toString()), null);
      }
    }
    );



    Action stopProcess =
      new AbstractAction()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (stopButton.isVisible())
        {
          try
          {
            currentProcess.destroy();
            stopButton.setVisible(false);
            currentProcess = null;
          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Process:Stopping Error");
            stopButton.setVisible(false);
            currentProcess = null;
          }
        }
      }
    };
    stopButton.addActionListener(stopProcess);
    stopButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "stopProcess");
    stopButton.getActionMap().put("stopProcess", stopProcess);
    Action undoAction =
      new AbstractAction()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null && activeNode.undo.canUndo())
        {
          try
          {
            activeNode.undo.undo();
          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Code:Undo Error");
          }
        }
        else if (undo.canUndo())
        {
          try
          {
            undo.undo();
          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Code:Undo Error");
          }
        }
      }
    };
    InputMap codeInputMap = code.getInputMap(JComponent.WHEN_FOCUSED);
    ActionMap codeActionMap = code.getActionMap();
    codeInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, mask), "undoAction");
    codeActionMap.put("undoAction", undoAction);
    Action redoAction =
      new AbstractAction()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null && activeNode.undo.canRedo())
        {
          try
          {
            activeNode.undo.redo();
          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Code:Redo Error");
          }
        }
        else if (undo.canRedo())
        {
          try
          {
            undo.redo();
          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Code:Redo Error");
          }
        }
      }
    };

    codeInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Y, mask), "redoAction");
    codeActionMap.put("redoAction", redoAction);

    AbstractAction findAndReplaceAction =
      new AbstractAction()
    {
      public void actionPerformed(ActionEvent e)
      {
        JTextComponent text = (JTextComponent)e.getSource();

        if (text.isFocusOwner() == false)
          text.grabFocus();
        findAndReplaceDialog.showDialog(Ogmios.this);

      }
    };

    codeInputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F, mask), "findAndReplace");
    codeActionMap.put("findAndReplace", findAndReplaceAction);

    outLog.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, mask), "findAndReplace");
    outLog.getActionMap().put("findAndReplace", findAndReplaceAction);

    errTab.addChangeListener(
     new ChangeListener()
     {
       public void stateChanged(ChangeEvent e)
       {
         Component component;
         if ((component=errTab.getSelectedComponent()) == terminal)
         {
            terminal.setFocusToInput();
          }
          else if (component == inScroll)
          {
            inLog.requestFocus();
          }
        }
      }
      );

    errTab.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, mask), "SwitchToTerminal");
    errTab.getActionMap().put("SwitchToTerminal", 
     new AbstractAction()
     {
       public void actionPerformed(ActionEvent e)
       {
         errTab.setSelectedComponent(terminal);
       }
     }
     );

//File listeners
    newFile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (promptUntitledWorkSave() == false)
          return;
        JFileChooser fileDialog = OgmiosFileChooser.getFileDialog(".java | 'Java Files'");
        fileDialog.setDialogTitle("Create New File");
        if (fileDialog.showSaveDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
        {

          try
          {
            File javaFile;
            FileWriter writer = new FileWriter(javaFile = fileDialog.getSelectedFile() );
            writer.write("");
            writer.close();
            /*
            OgmiosNode node;
            treeModel.insertNodeInto(node = new OgmiosNode(javaFile.getCanonicalPath()), treeRoot, treeRoot.getChildCount());
            openDocument(node);
            node.setDefaultDocumentListener(createDefaultDocumentListener(node),true);
            node.setUndo(true);*/
            OgmiosNode node;
            treeModel.insertNodeInto(node=createNode(javaFile.getCanonicalPath(), ""), treeRoot, treeRoot.getChildCount());
            openDocument(node);
          }
          catch (IOException ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Saving Error");
          }
        }
       // OgmiosUtilities.clearFileDialog();
      }
    }
    );
    blankDocument.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (promptUntitledWorkSave() == false)
          return;
        if (activeNode != null)
        {
          activeNode.verticalPosition = (codeScroll.getVerticalScrollBar()).getValue();
          activeNode.horizontalPosition = (codeScroll.getHorizontalScrollBar()).getValue();
          activeNode = null;
        }
        codeTab.setSelectedComponent(true);
    //    codeTab.setSelectedComponent(true);
        Document codeDocument;
        code.setDocument(codeDocument = code.createDefaultDocument());
        codeDocument.addUndoableEditListener(undo);
        tree.validate();
        tree.repaint();
      }
    }
    );
    templateManager.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (promptUntitledWorkSave() == false)
          return;
        Component focused = Ogmios.this.getFocusOwner();
        getJavaTemplateManager().showTemplateManager(treeRoot);
        focused.requestFocus();
      }
    }
    );
    openFile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (promptUntitledWorkSave() == false)
          return;

        JFileChooser fileDialog = OgmiosFileChooser.getFileDialog(".java | 'Java Files'");
        fileDialog.setDialogTitle("Open File");
        if (fileDialog.showOpenDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
        {
          File[] javaFiles;
          File javaFile;
          int i;
          for (i = 0; i < (javaFiles = fileDialog.getSelectedFiles()).length - 1; i++)
          {
            javaFile = javaFiles[i];
            try
            {
              if (javaFile.exists())
              {
                /*
                OgmiosNode node;
                treeModel.insertNodeInto(node = new OgmiosNode(javaFile.getCanonicalPath()), treeRoot, treeRoot.getChildCount());
                FileInputStream input = new FileInputStream(javaFile);
                code.getEditorKit().read(input, node.document, 0);
                input.close();

                node.document.putProperty(DefaultEditorKit.EndOfLineStringProperty, OgmiosUtilities.newLine);
                node.setDefaultDocumentListener(createDefaultDocumentListener(node),true);
                node.setUndo(true);
                */
                OgmiosNode node;
                treeModel.insertNodeInto(node=createNodeFromFile(javaFile), treeRoot, treeRoot.getChildCount());
                openDocument(node);
              }
            }

            catch (Throwable ex)
            {
              OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Reading Error");
            }
          }
       //   OgmiosUtilities.clearFileDialog();
          javaFile = javaFiles[i];
          try
          {
            if (javaFile.exists())
            {
              OgmiosNode node;
              treeModel.insertNodeInto(node = new OgmiosNode(javaFile.getCanonicalPath()), treeRoot, treeRoot.getChildCount());
              FileInputStream input = new FileInputStream(javaFile);
              code.getEditorKit().read(input, node.document, 0);
              input.close();
              node.document.putProperty(DefaultEditorKit.EndOfLineStringProperty, System.getProperty("line.separator"));
              node.setDefaultDocumentListener(createDefaultDocumentListener(node), true);
              node.setUndo(true);
              openDocument(node);

            }
          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Reading Error");
          }
        }
    //    OgmiosUtilities.clearFileDialog();
      }
    }
    );
    saveFile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
          save(activeNode);
        else if (code.getText().length() > 0)
        {
          saveCurrentDocumentToNode("Save Untitled File");
/*
          JFileChooser fileDialog = OgmiosFileChooser.getFileDialog(".java | 'Java Files'");

          fileDialog.setDialogTitle("Save Untitled File");
          if (fileDialog.showSaveDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
          {
            try
            {
              File javaFile;
              FileWriter writer = new FileWriter(javaFile = fileDialog.getSelectedFile() );
              writer.write(code.getText());
              writer.close();
              OgmiosNode node;
              treeModel.insertNodeInto(node = new OgmiosNode(javaFile.getCanonicalPath()), treeRoot, treeRoot.getChildCount());
              node.document = code.getDocument();
              node.verticalPosition = (codeScroll.getVerticalScrollBar()).getValue();
              node.horizontalPosition = (codeScroll.getHorizontalScrollBar()).getValue();
              activeNode = node;
              codeTab.setSelectedComponent(true);
              node.setDefaultDocumentListener(createDefaultDocumentListener(node), true);
              node.setUndo(true);
              //tree.expandPath(new TreePath(((DefaultMutableTreeNode)node.getParent()).getPath()));
              tree.scrollPathToVisible(new TreePath(node.getPath()));
              tree.repaint();
            }
            catch (IOException ex)
            {
              OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Saving Error");
            }
          }*/
        }
      }
    }
    );
    saveAsFile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
        {
           JFileChooser fileDialog = OgmiosFileChooser.getFileDialog(".java | 'Java Files'");

          fileDialog.setDialogTitle("Save File As...");
          if (fileDialog.showSaveDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
          {
            try
            {
              activeNode.adjustName(fileDialog.getSelectedFile().getCanonicalPath());
              treeModel.nodeChanged(activeNode);
              save(activeNode);
            }
            catch (Throwable ex)
            {
              OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Saving Error");
            }
          }
        }
        else if (code.getText().length() > 0)
        {
          saveCurrentDocumentToNode("Save Untitled File");
          /*
           JFileChooser fileDialog = OgmiosFileChooser.getFileDialog(".java | 'Java Files'");
          fileDialog.setDialogTitle("Save Untitled File");
          if (fileDialog.showSaveDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
          {
            try
            {
              File javaFile;
              FileWriter writer = new FileWriter(javaFile = fileDialog.getSelectedFile() );
              writer.write(code.getText());
              writer.close();
              OgmiosNode node;
              treeModel.insertNodeInto(node = new OgmiosNode(javaFile.getCanonicalPath()), treeRoot, treeRoot.getChildCount());
              node.document = code.getDocument();
              node.verticalPosition = (codeScroll.getVerticalScrollBar()).getValue();
              node.horizontalPosition = (codeScroll.getHorizontalScrollBar()).getValue();
              node.setDefaultDocumentListener(createDefaultDocumentListener(node), true);
              activeNode = node;
              codeTab.setSelectedComponent(true);


              tree.scrollPathToVisible(new TreePath(node.getPath()));


            }

            catch (IOException ex)
            {
              OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Saving Error");
            }
          }*/
        }
      }
    }
    );
    renameFile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
        {
          JFileChooser fileDialog = OgmiosFileChooser.getFileDialog(".java | 'Java Files'");

          fileDialog.setDialogTitle("Rename " + activeNode.name);
          if (fileDialog.showSaveDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
          {
            try
            {
              File f;
              new File(activeNode.fullName()).renameTo(f = fileDialog.getSelectedFile());
              activeNode.adjustName(f.getCanonicalPath());
              save(activeNode);
              treeModel.nodeChanged(activeNode);
            }
            catch (Throwable ex)
            {
              OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Saving Error");
            }

          }

        }

      }
    }
    );
    printFile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        try
        {
          code.print(false);
        }
        catch (Throwable ex)
        {
          OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Print:Printing Error");
        }

      }
    }
    );
    printSelectedText.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        try
        {
          code.print(true);
        }
        catch (Throwable ex)
        {
          OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Print:Printing Error");
        }
      }
    }
    );

    closeMultipleFiles.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {

        List<List<Object>> slots = new ArrayList<List<Object>>();
        for (Enumeration children = treeRoot.preorderEnumeration(); children.hasMoreElements();)
        {
          TreeNode node = (TreeNode) children.nextElement();
          if (node instanceof OgmiosNode)
          {
            List<Object> miniList = new ArrayList<Object>(3);
            OgmiosNode ogmiosNode = (OgmiosNode) node;
            miniList.add(ogmiosNode.name + " (" + ogmiosNode.directory  + File.separator +  ")");
            miniList.add(true);
            if (ogmiosNode.saveNeeded)
              miniList.add(true);
            else
              miniList.add(null);
            miniList.add(ogmiosNode);
            slots.add(miniList);
          }
        }

        if (slots.size() > 0)
        {
          final JDialog closePrompt = new JDialog();
          closePrompt.setTitle("Close Documents");
          closePrompt.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);


          class CloseTableModel extends AbstractTableModel
          {

            private final String[] labels = new String[] {"Document", "Close", "Save"};

            public final List<List<Object>> slots;

            public CloseTableModel(List<List<Object>> slots)
            {
              this.slots = slots;
            }

            public String getColumnName(int column)
            {
              return labels[column];
            }

            public int getColumnCount()
            {
              return 3;
            }
            public int getRowCount()
            {
              return slots.size();
            }

            public Object getValueAt(int row, int column)
            {
              return slots.get(row).get(column);

            }

            public Class getColumnClass(int c)
            {
              return c == 0 ? String.class : Boolean.class;//getValueAt(0, c).getClass();
            }

            public void setValueAt(Object value, int row, int column)
            {
              slots.get(row).set(column, value);
              fireTableCellUpdated(row, column);
            }
            public boolean isCellEditable(int row, int column)
            {
              return column != 0 && slots.get(row).get(column) != null;
            }

          }

          final JTable table =
            new JTable(new CloseTableModel(slots))
          {
            {

              JTableHeader header = getTableHeader();
              header.setReorderingAllowed(false);
              TableColumnModel model = header.getColumnModel();
              header.addMouseListener(
                new MouseAdapter()
              {
                boolean saveClick = true;
                boolean closeClick = true;
                public void mousePressed(MouseEvent e)
                {
                  if (e.getClickCount() == 2)
                  {

                    int selection =  ((JTableHeader)e.getSource()).getColumnModel().getColumnIndexAtX(e.getX());

                    if (selection == 1)
                    {
                      closeClick = !closeClick;
                      for (int i = 0; i < getRowCount(); i++)
                      {
                        setValueAt(closeClick, i, 1);
                      }
                    }
                    else if (selection == 2)
                    {
                      saveClick = !saveClick;
                      for (int i = 0; i < getRowCount(); i++)
                      {
                        if (getValueAt(i, 2) != null)
                          setValueAt(saveClick, i, 2);
                      }
                    }
                  }
                }
              }
              );


            }

            public TableCellRenderer getCellRenderer(int row, int column)
            {
              TableModel model = getModel();
              Object value = model.getValueAt(row, column);

              return getDefaultRenderer(value == null ? String.class : model.getColumnClass(column));

            }
          };

          table.setRowHeight(table.getFontMetrics(table.getFont()).getHeight() + 10);
//	table.setFillsViewportHeight(true);
          Container contents = closePrompt.getContentPane();
          contents.add(new JScrollPane(table));
          JButton closePromptFiles = new JButton("Close Files");
          closePromptFiles.addActionListener(
            new ActionListener()
          {
            public void actionPerformed(ActionEvent e)
            {
              JButton button = (JButton)e.getSource();
              button.setEnabled(false);
              closePrompt.setVisible(false);

            }
          }
          );
          JPanel labelPanel = new JPanel(new BorderLayout());
          labelPanel.add(closePromptFiles, BorderLayout.NORTH);
          labelPanel.add(new JLabel("Check 'Close' to close the file. Check 'Save' to save the file, if you are closing"), BorderLayout.SOUTH);

          contents.add(labelPanel, BorderLayout.NORTH);
          closePrompt.pack();
          Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
          closePrompt.setSize(new Dimension(screenSize.width / 3, screenSize.height / 3));
          closePrompt.setModal(true);
          closePrompt.setLocationRelativeTo(Ogmios.this);
          closePrompt.setVisible(true);
          if (closePromptFiles.isEnabled() == false)
            for (Iterator<List<Object>> lists = slots.iterator(); lists.hasNext();)
            {
              for (Iterator<Object> stack = lists.next().iterator(); stack.hasNext();)
              {
                stack.next();//don't need. It's the document's name.
                if (((Boolean)stack.next()) == true)
                {
                  Boolean saveNeeded = (Boolean)stack.next();
                  OgmiosNode node = (OgmiosNode)stack.next();
                  if (saveNeeded != null && saveNeeded == true)
                    save(node);
                  closeDocumentUnprompted(node);
                }
                else
                {
                  stack.next();
                  stack.next();
                }
              }
            }

        }
      }
    }
    );


    closeFile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
        {
          closeDocument(activeNode);
        }
      }
    }
    );
    exitOgmios.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        processWindowEvent(new WindowEvent(Ogmios.this, WindowEvent.WINDOW_CLOSING));
      }
    }
    );


//Compile

    compileAndRun.addActionListener(
      new ActionListener()
    {
      final class CompileAndRunProcessWaiter extends ProcessWaiter
      {

        public void run()
        {
          super.run();


          new Thread(runThread).start();

        }

      }

      public void actionPerformed(ActionEvent e)
      {

        if (activeNode != null)
        {
          save(activeNode);
          String[] args;

          String path = compilerDirectory.length() == 0 ? 
          OgmiosUtilities.getBasePackagePath(activeNode.directory + File.separator, javaPackage) : compilerDirectory;
          args = new String[6 + javacArgs.length];
          args[0] = jAddress + File.separator + "javac";
          args[1] = "-sourcepath";
          args[2] = path + File.pathSeparator +  sourcePath;
          args[3] = "-classpath";
          args[4] = path+ File.pathSeparator + classPath;
          for (int i = 0; i < javacArgs.length; i++)
            args[5 + i] = javacArgs[i];
          args[args.length - 1] = activeNode.fullName();


          runProcess(args, null, new File(path), new CompileAndRunProcessWaiter());
        }
        else
        {
          saveFile.doClick();
          if (activeNode != null)
          {
            save(activeNode);
            String[] args;
          

            String path = compilerDirectory.length()==0 ? 
           OgmiosUtilities.getBasePackagePath(activeNode.directory + File.separator,javaPackage) : compilerDirectory;
            args = new String[6 + javacArgs.length];
            args[0] = jAddress + File.separator + "javac";
            args[1] = "-sourcepath";
            args[2] = path+ File.pathSeparator +  sourcePath;
            args[3] = "-classpath";
            args[4] = path+ File.pathSeparator + classPath;

            for (int i = 0; i < javacArgs.length; i++)
              args[5 + i] = javacArgs[i];
            args[args.length - 1] = activeNode.fullName();


            runProcess(args, null, new File(path),
                       new CompileAndRunProcessWaiter()
                      );
          }

        }
      }
    }
    );


    compile.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent event)
      {

        if (activeNode != null)
        {
          save(activeNode);
          String[] args;
      
         String path = compilerDirectory.length() == 0 ?
         OgmiosUtilities.getBasePackagePath(activeNode.directory + File.separator,javaPackage) : compilerDirectory;
         args = new String[6 + javacArgs.length];
          args[0] = jAddress + File.separator + "javac";
          args[1] = "-sourcepath";
          args[2] =path + File.pathSeparator +  sourcePath;
          args[3] = "-classpath";
          args[4] = path + File.pathSeparator + classPath;

          for (int i = 0; i < javacArgs.length; i++)
            args[5 + i] = javacArgs[i];
          args[args.length - 1] = activeNode.fullName();
          runProcess(args, null, new File(path));

        }
        else
        {
          saveFile.doClick();
          if (activeNode != null)
          {
            save(activeNode);
            String[] args;

            String path = compilerDirectory.length() == 0 ?
            OgmiosUtilities.getBasePackagePath(activeNode.directory + File.separator,javaPackage): compilerDirectory;

            args = new String[6 + javacArgs.length];
            args[0] = jAddress + File.separator + "javac";
            args[1] = "-sourcepath";
            args[2] = path + File.pathSeparator +  sourcePath;
            args[3] = "-classpath";
            args[4] = path + File.pathSeparator + classPath;

            for (int i = 0; i < javacArgs.length; i++)
              args[5 + i] = javacArgs[i];
            args[args.length - 1] = activeNode.fullName();
            runProcess(args, null, new File(path));

          }
        }
      }
    }
    );

    run.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
        {
          if (new File(activeNode.directory + File.separator + activeNode.nameWithoutExtension() + ".class").exists())
          {
            if (runInOutputTab.getState())
              codeTab.setSelectedComponent(false);
            String[] args;

            String path = executionerDirectory.length() == 0 ?
             OgmiosUtilities.getBasePackagePath(activeNode.directory + File.separator,javaPackage)  : executionerDirectory;

            args = new String[4 + javaArgs.length + appArgs.length];
            args[0] = jAddress + File.separator + "java";
            args[1] = "-cp";
            args[2] =path + File.pathSeparator + classPath;
            int i;
            int index = 2;

            for (i = 0; i < javaArgs.length; i++)
            {
              args[++index] = javaArgs[i];

            }
            args[++index] = javaPackage + activeNode.nameWithoutExtension() ;
            for (i = 0; i < appArgs.length; i++)
            {
              args[++index] = appArgs[i];
            }


            runProcess(args, null, new File(path));

          }
        }
      }
    }
    );

    runInAppletViewer.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
        {
          if (new File(activeNode.directory + File.separator + activeNode.nameWithoutExtension() + ".class").exists())
          {
            if (runInOutputTab.getState())
              codeTab.setSelectedComponent(false);
            runProcess(new String[] {jAddress + File.separator + "appletviewer", activeNode.fullName()}, null, 
           new File(appletViewerDirectory.length() == 0 ? OgmiosUtilities.getBasePackagePath(activeNode.directory + File.separator, javaPackage) : appletViewerDirectory) );
          }
        }
      }
    }
    );


//settings
    compilerArgs.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String[] arr;
        if ((arr = ListDialog.showDialog(javacArgs, "Arguments For Javac", "These are arguments for Javac. A default sourcepath is implicitly provided.")) != ListDialog.emptyStringArray)
          javacArgs = arr;
      }
    }
    );
    executionerArgs.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String[] arr;
        if ((arr = ListDialog.showDialog(javaArgs, "Arguments for Java", "These are arguments for Java. A default classpath is implicitly provided")) != ListDialog.emptyStringArray)
          javaArgs = arr;
      }
    }
    );
    packageArg.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String s;
        if ((s = JOptionPane.showInputDialog(Ogmios.this, "Enter the name of the packages to attach to the name of your application", javaPackage)) != null)
        {
          if (s.length() > 0 && s.charAt(s.length() - 1) != '.')
            javaPackage = s + ".";
          else
            javaPackage = s;
        }
      }
    }
    );
    sourcePathArg.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String s;
        if ((s = JOptionPane.showInputDialog(Ogmios.this, "Enter the sourcepath", sourcePath)) != null)
          sourcePath = s;
      }
    }
    );
    classPathArg.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String s;
        if ((s = JOptionPane.showInputDialog(Ogmios.this, "Enter the classpath", classPath)) != null)
          classPath = s;
      }
    }
    );

    compilerDirectoryArg.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String s;
        if ((s = JOptionPane.showInputDialog(Ogmios.this, "Enter the compiler's working directory", compilerDirectory)) != null)
          compilerDirectory = s;
      }
    }
    );
    
    executionerDirectoryArg.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String s;
        if ((s = JOptionPane.showInputDialog(Ogmios.this, "Enter the executioner's working directory", executionerDirectory)) != null)
          executionerDirectory = s;
      }
    }
    );

    appletViewerDirectoryArg.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String s;
        if ((s = JOptionPane.showInputDialog(Ogmios.this, "Enter the appletviewer's working directory", appletViewerDirectory)) != null)
          appletViewerDirectory = s;
      }
    }
    );

    postArgs.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String[] arr;
        if ((arr = ListDialog.showDialog(appArgs, "Arguments for Application", "These are arguments for your Application.")) != ListDialog.emptyStringArray)
          appArgs = arr;
      }
    }
    );
    autoLocateJDK.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String loc = System.getProperty("java.home");
        if (loc != null)
        {
          File f;

          if ((f = new File(loc)).getName().equalsIgnoreCase("jre"))
          {
            String s;
            String s1;
            if ((s = f.getParent()) != null && (new File(s1 = ((s = s + File.separator + "bin") + File.separator + "javac")).exists() || new File(s1 + ".exe").exists()   ))
              settingsMap.put("javaAddress", jAddress = s);
            else
              JOptionPane.showMessageDialog(Ogmios.this, "Could not auto-locate JDK Bin. \nYou will need to manually locate the JDK Bin", "System: Auto-Locate Error", JOptionPane.ERROR_MESSAGE);
          }
          else
            try
            {
              String s = f.getCanonicalPath() + File.separator + "bin";
              String s1 = s + File.separator +  "javac";
              if (new File(s1).exists() || new File(s1 + ".exe").exists())
                settingsMap.put("javaAddress", jAddress = s);
              else
                JOptionPane.showMessageDialog(Ogmios.this, "Could not auto-locate JDK Bin. \nYou will need to manually locate the JDK Bin", "System: Auto-Locate Error", JOptionPane.ERROR_MESSAGE);
            }
            catch (IOException ex)
            {
              OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO: Path Errors");
            }
        }
        else
        {
          JOptionPane.showMessageDialog(Ogmios.this, "Could not auto-locate JDK Bin. \nYou will need to manually locate the JDK Bin", "System: Auto-Locate Error", JOptionPane.ERROR_MESSAGE);
        }
      }
    }
    );
    locateJDKManually.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        JFileChooser folderDialog = OgmiosFileChooser.getFolderDialog();
       folderDialog.setMultiSelectionEnabled(false);
        if (folderDialog.showOpenDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
        {
          try
          {
            File f = folderDialog.getSelectedFile();
            jAddress = f.getCanonicalPath();
            settingsMap.put("javaAddress", jAddress);
          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Directory Error");
          }
        }
      }
    }
    );

   splitCodeTab.addItemListener(
     new ItemListener()
     {
      public void itemStateChanged(ItemEvent e)
      {
        ogmiosGUI.codeTab.splitTabs(ogmiosGUI.splitCodeTab.getState());
      }
     }
     );


    setReactionsSettings =
      new ItemListener()
    {
      public void itemStateChanged(ItemEvent e)
      {
        JCheckBoxMenuItem source = ((JCheckBoxMenuItem)e.getSource());
        settingsMap.put(source.getText(), OgmiosUtilities.booleanNumberString(source.getState()));
      }
    };

    setRadioSettings =
      new ItemListener()
    {
      public void itemStateChanged(ItemEvent e)
      {
        if (e.getStateChange() == ItemEvent.SELECTED)
        {
          JRadioButtonMenuItem source = (JRadioButtonMenuItem)e.getSource();
          JMenu box;
          settingsMap.put((box = ((JMenu)((JPopupMenu)source.getParent()).getInvoker())).getText(), Integer.toString(OgmiosUtilities.getJMenuItemIndex(box, source)));
        }
      }
    };


    ActionListener LookAndFeel =
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        try
        {
          String laf = ((LAFRadioButtonMenuItem)e.getSource()).lookAndFeel;
          UIManager.setLookAndFeel(laf);
          settingsMap.put("ogmiosLAF", laf);
          SwingUtilities.updateComponentTreeUI(Ogmios.this);
        //  SwingUtilities.updateComponentTreeUI(OgmiosUtilities.folderDialog);
      //    SwingUtilities.updateComponentTreeUI(OgmiosUtilities.fileDialog);
          if (munchkin != null)
            SwingUtilities.updateComponentTreeUI(Ogmios.this.munchkin);
          if (javaTemplateManager != null)
           SwingUtilities.updateComponentTreeUI(javaTemplateManager);
          if (archiveBuilder != null)
           SwingUtilities.updateComponentTreeUI(archiveBuilder);
          SwingUtilities.updateComponentTreeUI(Ogmios.this.findAndReplaceDialog);
        }
        catch (Throwable ex)
        {

        }
      }
    };

    saveSettingsManually.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        saveSettings();
      }
    }
    );

//Tools
    gotoLine.addActionListener(

      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {

        String val = JOptionPane.showInputDialog(Ogmios.this, "Enter line to jump to", "Goto Line", JOptionPane.INFORMATION_MESSAGE);
        if (val != null && val.length() > 0)
        {
          int i = OgmiosUtilities.tryParse(val);
          if (OgmiosUtilities.success)
          {
            if (OgmiosUtilities.gotoLine(code, i))
             codeTab.setSelectedComponent(true);
          }
        }
      }
    }
    );
    buildZip.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        getArchiveBuilder().showDialog(Ogmios.this, "Zip");
      }
    }
    );
    buildJar.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        getArchiveBuilder().showDialog(Ogmios.this, "Jar");
      }
    }
    );
      

    insertAppletTag.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
        {
          try
          {
            code.getDocument().insertString(0, "/*\n <applet code=\"" + activeNode.nameWithoutExtension() + ".class\"" + " width=\"300\" height=\"300\">\n \n <" + "/applet>\n*/\n", null);
          }
          catch (BadLocationException ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Code:Insert Error");
          }
        }
      }
    }
    );


    publishInHTML.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        if (activeNode != null)
        {
          int start;
          int end;
          int closeApplet;
          try
          {
            String text = activeNode.document.getText(0, activeNode.document.getLength());
            if (text.length() > 0)
            {

              text = text.toLowerCase();
              if ((start = text.indexOf("<applet")) != -1 && (closeApplet = text.indexOf(">", start + 7)) != -1 && (end = text.indexOf("</applet>", closeApplet + 1 )) != -1)
              {
                Document doc = new PlainDocument();
                doc.insertString(0, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"" +
                                 " \"http:" + "//www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title>" + activeNode.nameWithoutExtension() + "</title>"
                                 + "\n<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\" />\n</head>\n<body>\n" + activeNode.document.getText(start, end + 9 - start) + "\n</body>\n</html>", null);
                FileWriter out = new FileWriter(new File(activeNode.directory + File.separator + activeNode.nameWithoutExtension() + "HTML.html"));
                code.getEditorKit().write(out, doc, 0, doc.getLength());
                out.close();

              }
            }

          }
          catch (Throwable ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Writing Error");
          }

        }
      }
    }
    );

    launchMacroScripter.addActionListener(
     new ActionListener()
     {
       public void actionPerformed(ActionEvent e)
       {
         MacroScripter scripter = new MacroScripter();
         scripter.setIconImage(getIconImage());
         scripter.setVisible(true);
       }
     }
     );

//About
    help.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        help.setEnabled(false);
        FolderNavigator fd = FolderNavigator.showDialog("Help");
        fd.addWindowListener(
          new WindowAdapter()
        {
          public void windowClosed(WindowEvent e)
          {
            help.setEnabled(true);
          }
        }
        );
        fd.setIconImage(getIconImage());
      }
    }
    );

    about.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        JOptionPane.showMessageDialog(Ogmios.this, "Pay No Attention To That Man Behind The Curtain!\n\nOgmios - A Java IDE  v" + OGMIOS_VERSION + " \"" + OGMIOS_PSEUDONYM +  "\"\n\nDesigned by: The Fozzy Team\nMike Capasso\nOliver Kubik\nZach Littrell", "About", JOptionPane.INFORMATION_MESSAGE);
      }
    }
    );


//Plugins

    buildExtension.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        //String extensionName = getMunchkin().build(Ogmios.this, "Extension");
          MunchCapsule munchCapsule = getMunchkin().build(Ogmios.this, "Extension");
          if (munchCapsule != null)
          {
            tryToLoad(munchCapsule);
          }
      }
    }
    );



  browseCommands.addActionListener(
   new ActionListener()
   {
     public void actionPerformed(ActionEvent e)
     {
      browseCommands.setEnabled(false);
       CommandBrowser browser = new CommandBrowser();
        browser.setVisible(true);
        browser.addWindowListener(
          new WindowAdapter()
        {
          public void windowClosed(WindowEvent e)
          {
            browseCommands.setEnabled(true);
          }
        }
        );
        browser.setIconImage(getIconImage());       
     }
   }
   );  

   buildCommand.addActionListener(
    new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
          MunchCapsule munchCapsule = getMunchkin().build(Ogmios.this, "Command");
          if (munchCapsule != null)
          {
            tryToLoad(munchCapsule);
          }
      }
    }
    );


//Acquiring user-settings
    String val;
    if ((val = settingsMap.get("javaAddress")) != null)
      jAddress = val;
    else if (JOptionPane.showConfirmDialog(Ogmios.this, "Ogmios does not have a JDK Bin location set up.\nDo you want to let Oz try to auto-locate the JDK Bin for you?", "Auto-Locate JDK?", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
      autoLocateJDK.doClick();

    ButtonGroup lookAndFeelGroup = new ButtonGroup();


    String laf = UIManager.getLookAndFeel().getClass().getName();

    for (UIManager.LookAndFeelInfo l : UIManager.getInstalledLookAndFeels())
    {
      LAFRadioButtonMenuItem itm = new LAFRadioButtonMenuItem(l.getClassName(), l.getName());

      lookAndFeelsSettings.add(itm);
      lookAndFeelGroup.add(itm);
      if (laf == l.getClassName())
        lookAndFeelGroup.setSelected(itm.getModel(), true);
      itm.addActionListener(LookAndFeel);
    }

    addProcessWatcher(compile);
    addProcessWatcher(compileAndRun);
    addProcessWatcher(run);
    addProcessWatcher(runInAppletViewer);

  }

  /**
   * Add checkbox to Reactions and add ItemListener, so the checkbox will 
   * set in the settings whether it is checked or unchecked 
   */
  public void addReaction(JCheckBoxMenuItem reaction)
  {
    reaction.addItemListener(setReactionsSettings);
    reactionsSettings.add(reaction);
  }

  /**
  * Remove checkbox from Reactions and remove ItemListener
  * added by addReaction.
  */
  public void removeReaction(JCheckBoxMenuItem reaction)
  {
    reactionsSettings.remove(reaction);
    reaction.removeItemListener(setReactionsSettings);
  }

  /**
  * Add radio button and add ItemListener, so the raido button
  * will set in the settings whether it is selected or not.
  */
  public void addErrLogRegex(RegexRadioButtonMenuItem regexButton)
  {
    errLogRegexGroup.add(regexButton);
    errLogRegex.add(regexButton);
    regexButton.addItemListener(setRadioSettings);
    if (errLogRegexGroup.getButtonCount() == 1)
      errLogRegexGroup.setSelected(regexButton.getModel(), true);
  }

  /**
  * Remove radio button and ItemListener added by addErrLogRegex
  */
  public void removeErrLogRegex(RegexRadioButtonMenuItem regexButton)
  {
    removeErrLogRegex(regexButton, null);
  }


  /**
  * Remove radio button and ItemListener added by addErrLogRegex, and set newSelection as the selected
  * button.
  */
  public void removeErrLogRegex(RegexRadioButtonMenuItem regexButton, RegexRadioButtonMenuItem newSelection)
  {
    errLogRegexGroup.remove(regexButton);
    errLogRegex.remove(regexButton);
    regexButton.removeItemListener(setRadioSettings);
    if (newSelection != null)
    {
      if (errLogRegexGroup.getButtonCount() > 0)
        errLogRegexGroup.setSelected(((JRadioButtonMenuItem)errLogRegex.getMenuComponent(0)).getModel(), true);
    }
    else
    {
      errLogRegexGroup.setSelected(newSelection.getModel(), true);
    }
  }

  /**
  * Create OgmiosNode to be used by Ogmios.
  */
  public OgmiosNode createNode(String path, String contents)
  {
    try
    {
      OgmiosNode node = new OgmiosNode(path);
      node.document.putProperty(DefaultEditorKit.EndOfLineStringProperty, System.getProperty("line.separator"));
      node.document.insertString(0, contents, SimpleAttributeSet.EMPTY);
      node.setDefaultDocumentListener(Ogmios.ogmiosGUI.createDefaultDocumentListener(node), true);
      node.setUndo(true);
      return node;
    }
    catch (BadLocationException ex)
    {
      OgmiosUtilities.showErrorBox(null, ex, "Document:Location Error");
    }
    return null;
  }
  public OgmiosNode createNodeFromFile(String path)
  {
    return createNodeFromFile(new File(path));
  }

  /**
  * Create OgmiosNode for Ogmios from the contents at file.
  */
  public OgmiosNode createNodeFromFile(File file)
  {
    try
    {
      return createNode(file.getCanonicalPath(), OgmiosUtilities.plainFileContents(file));
    }
    catch (IOException ex)
    {
      OgmiosUtilities.showErrorBox(null, ex, "IO: File Error");
    }
    return null;
  }


  /**
  * Use this if you want to close a node, regardless of whether its document has
  * unsaved changes.
  */
  public boolean closeDocumentUnprompted(OgmiosNode node)
  {
    treeModel.removeNodeFromParent(node);
    if (node == activeNode)
    {
      activeNode = null;
      Document codeDocument;
      code.setDocument(codeDocument = code.createDefaultDocument());
      codeDocument.addUndoableEditListener(undo);
    }
    tree.validate();
    return true;
  }

  /**
  * Use this if you want to close a node, but only if document is has no unsaved work
  * or the user discards the changes.
  */
  public boolean closeDocument(OgmiosNode node)
  {
    if (node.saveNeeded)
      switch (JOptionPane.showConfirmDialog(Ogmios.this, "Do you want to save " + node.name + "?", "Unsaved Changes", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
      {
      case JOptionPane.YES_OPTION:
        save(node);
        break;
      case JOptionPane.NO_OPTION:
        break;
      default:
        return false;
      }

    treeModel.removeNodeFromParent(node);
    if (node == activeNode)
    {
      activeNode = null;
      Document codeDocument;
      code.setDocument(codeDocument = code.createDefaultDocument());
      codeDocument.addUndoableEditListener(undo);
    }
    tree.validate();
    return true;
  }
  /**
  * Open node's document in Ogmios
  */
  public void openDocument(OgmiosNode o)
  {
    if (activeNode == null)
    {
      activeNode = o;
      codeTab.setSelectedComponent(true);
      code.setDocument(activeNode.document  );
      code.select(0, 0);
      SwingUtilities.invokeLater(scrollCode);
      tree.scrollPathToVisible(new TreePath(o.getPath()));
      tree.repaint();
    }
    else
    {

      if (o != activeNode)
        //if (o != treeRoot && o.isLeaf() && o != activeNode)
      {

        activeNode.verticalPosition = (codeScroll.getVerticalScrollBar()).getValue();
        activeNode.horizontalPosition = (codeScroll.getHorizontalScrollBar()).getValue();
        activeNode = o;
        codeTab.setSelectedComponent(true);
        code.setDocument(activeNode.document  );
        code.select(0, 0);
        SwingUtilities.invokeLater(scrollCode);
        tree.scrollPathToVisible(new TreePath(o.getPath()));
        tree.repaint();
      }
    }
  }


  /**
  * Save document in node.
  */
  public void save(OgmiosNode node)
  {
    try
    {
      FileWriter out = new FileWriter(new File(node.fullName()));
      code.getEditorKit().write(out, node.document, 0, node.document.getLength());
      out.close();
      node.setSaved(true);
      tree.repaint();
    }
    catch (Throwable ex)
    {
      OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Saving Error");
    }

  }


  /**
   * Opens up a process ran under Ogmios's interface.
   * @param	arguments	The first element is the filename of the application being launched, while the following elements
   *				are the command line arguments.
   */
  public boolean runProcess(String[] arguments, String[] environment, File workingDirectory)
  {
   if (stopButton.isVisible())
   {
    return false;
   }
    try
    {

      currentProcess = Runtime.getRuntime().exec(arguments, environment, workingDirectory);

      if (EventQueue.isDispatchThread())
        clearGUI.run();
      else
        try
        {
          SwingUtilities.invokeAndWait(clearGUI);
        }
        catch (Throwable ex)
        {
          OgmiosUtilities.showErrorBox(Ogmios.this, ex, "GUI:Clearing Error");
          return false;
        }

      processWriter = new OutputWriter();
      inThread = new InputThread();
      errThread = new ErrorThread();
      waitThread = new ProcessWaiter();

      inThread.start();
      errThread.start();
      waitThread.start();


    }
    catch (IOException e)
    {
      OgmiosUtilities.showErrorBox(Ogmios.this, e, "Process:Starting Error");
      stopButton.setVisible(false);
      return false;
    }
    return true;
  }
  
  /**
  * Open process in Ogmios, launching the passed thread when the process starts.
  */
  public boolean runProcess(String[] arguments, String[] environment, File workingDirectory, Thread processWaiter)
  {
   if (stopButton.isVisible())
    return false;
    try
    {

      currentProcess = Runtime.getRuntime().exec(arguments, environment, workingDirectory);

      if (EventQueue.isDispatchThread())
        clearGUI.run();
      else
        try
        {
          SwingUtilities.invokeAndWait(clearGUI);
        }
        catch (Throwable ex)
        {
          OgmiosUtilities.showErrorBox(Ogmios.this, ex, "GUI:Clearing Error");
          return false;
        }

      processWriter = new OutputWriter();
      inThread = new InputThread();
      errThread = new ErrorThread();
      waitThread = processWaiter;

      inThread.start();
      errThread.start();
      waitThread.start();


    }
    catch (IOException e)
    {
      OgmiosUtilities.showErrorBox(Ogmios.this, e, "Process:Starting Error");
      stopButton.setVisible(false);
      return false;
    }
    return true;
  }


  /**
  * Ogmios's default ProcessWaiter
  */
  protected class ProcessWaiter extends Thread
  {
    public volatile boolean isExecuting = false;
    public void run()
    {
      try
      {
        isExecuting = true;
        int c = currentProcess.waitFor();
        try
        {

          SwingUtilities.invokeAndWait(stopButtonDisabler);

        }
        catch (Throwable ex)
        {
          OgmiosUtilities.showErrorBox(Ogmios.this, ex, "GUI:Updating Error");
        }

        while (inThread.isAlive() && errThread.isAlive())
        {

        }

      }
      catch (InterruptedException ex)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Process:Waiting Error");
      }


      try
      {
        updateGUI.enable = true;
        SwingUtilities.invokeAndWait(updateGUI);
      }
      catch (Throwable ex)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, ex, "GUI:Updating Error");
      }
      isExecuting = false;
    }

  }

  /**
  * Ogmios default writer to processes' output stream
  */
  protected class OutputWriter
  {
    private BufferedWriter out;

    public OutputWriter()
    {

      out = new BufferedWriter(new OutputStreamWriter(currentProcess.getOutputStream()));

    }

    public OutputWriter(Process process)
    {
      out = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
    }

    public void write()
    {
      if (printInputOnOutput.getState())
      {
        outLog.append(inLog.getText());
      }

      try
      {
        out.write(inLog.getText());
        out.flush();
      }
      catch (IOException ex)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Process:Input Error");
      }

    }
  }

  /**
  * Ogmios' default listener to a process' input thread
  */
  protected class InputThread extends Thread
  {
    protected BufferedReader input;
    protected InputStream in;
    protected Runnable updater;
    protected int bufferSize;
    protected char[] buffer = new char[1024];
    public InputThread(InputStream inputStream)
    {
      input = new BufferedReader(new InputStreamReader(in = inputStream));
      setDaemon(true);
    }
    public InputThread()
    {
      input = new BufferedReader(new InputStreamReader(in = currentProcess.getInputStream()));
      updater = new Runnable()
      {
        public void run()
        {
          //    outLog.setCaretPosition(outDocument.getLength());
          // outLog.replaceSelection(new String(buffer, 0, bufferSize));
          outLog.append(new String(buffer, 0, bufferSize));
        }
      };
      setDaemon(true);
    }
    public void run()
    {
//int length;
      try
      {
        while ((bufferSize = input.read(buffer, 0, 1024)) != -1)
        {

          SwingUtilities.invokeAndWait(updater);

        }

        input.close();
      }
      catch (InterruptedException e)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, e, "Process:Input Error");
      }
      catch (InvocationTargetException e)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, e, "Process:Input Error");
      }
      catch (IOException ex)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Process:Input Error");
      }
      catch (Throwable ex)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Process:Input Error");
      }
    }
  }

  /**
  * Ogmios' default listener to a process' error stream
  */
  protected class ErrorThread extends Thread
  {
    protected BufferedReader err;
    protected Runnable updater;
    protected String line;
    public ErrorThread(InputStream error)
    {
      err = new BufferedReader(new InputStreamReader(error));
    }
    public ErrorThread()
    {
      err = new BufferedReader(new InputStreamReader(currentProcess.getErrorStream()));
      updater =
        new Runnable()
      {
        public void run()
        {

          errLogList.addElement(line);
          if (errTab.getSelectedIndex() != 0 && showNewErrors.getState())
          {
            errTab.setSelectedIndex(0);
          }
        }
      };
      setDaemon(true);
    }
    public void run()
    {
      try
      {


        while ((line = err.readLine()) != null)
        {
          try
          {

            SwingUtilities.invokeAndWait(updater);

          }
          catch (InterruptedException ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Process:Error Stream Error");
          }
          catch (InvocationTargetException e)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, e, "Process:Error Stream Error");
          }
        }
        err.close();
      }
      catch (IOException ex)
      {
        OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Process:Error Stream Error");
      }
    }
  }

 
  /**
  * This class encapsulates a document that Ogmios can open and manipulate.
  */
  public static class OgmiosNode extends DefaultMutableTreeNode implements Savable
  {
    public String name;
    public String directory;
    public Document document;
    public UndoManager undo = new UndoManager();

    public DocumentListener defaultDocumentListener;

    public int verticalPosition = 0;
    public int horizontalPosition = 0;
    public boolean saveNeeded = false;
    public OgmiosNode (String fileName)
    {
      adjustName(fileName);
      document = new DefaultStyledDocument();
      document.putProperty(DefaultEditorKit.EndOfLineStringProperty, System.getProperty("line.separator"));
      undo.setLimit(MAX_UNDO_LEVEL);
    }
    
    /**
    * Use this if you want to change both name and directory from one file name.
    */
    public void adjustName(String fileName)
    {
      int i = fileName.lastIndexOf(File.separator);
      if  (i != -1)
      {
        name = fileName.substring(i + 1);
        directory = fileName.substring(0, i);
      }
      else
      {
        name = fileName;
        directory = "";
      }
    }
    public void setUndo(boolean enable)
    {
      if (enable)
        document.addUndoableEditListener(undo);
      else
        document.removeUndoableEditListener(undo);
    }
    public void setDefaultDocumentListener(DocumentListener newDocumentListener, boolean add)
    {
      defaultDocumentListener = newDocumentListener;
      if (add)
        document.addDocumentListener(newDocumentListener);
    }
    public void setSaved(boolean saved)
    {
      if (saved && saveNeeded)
      {
        document.addDocumentListener(defaultDocumentListener);
        saveNeeded = false;
      }
      else if (saved == false && saveNeeded == false)
      {
        document.removeDocumentListener(defaultDocumentListener);
        saveNeeded = true;
      }
    }
    public final String toString()
    {
      return name;
    }
    public final String fullName()
    {
      return directory + File.separator + name;
    }
    public final String nameWithoutExtension()
    {
      int lastIndex = name.lastIndexOf(".");
      return lastIndex != -1 ? name.substring(0, lastIndex) : name;
    }
    public void save()
    {
      Ogmios.ogmiosGUI.save(this);
    }
    public boolean saveNeeded()
   {
     return saveNeeded;
   }
  }


  /**
  * Adds a document listener to the document inside the node, listening for changes.
  */
  public DocumentListener createDefaultDocumentListener(final OgmiosNode node)
  {
    return new DocumentListener()
    {
      public void changedUpdate(DocumentEvent e)
      {
      }
      public void insertUpdate(DocumentEvent e)
      {
        node.saveNeeded = true;
        node.document.removeDocumentListener(this);
        treeModel.nodeChanged(node);
      }
      public void removeUpdate(DocumentEvent e)
      {
        node.saveNeeded = true;
        node.document.removeDocumentListener(this);
        treeModel.nodeChanged(node);
      }
    };
  }

  /**
  * Add a component that should be disabled if Ogmios is running a process
  */
  public void addProcessWatcher(Component component)
  {
    processWatchers.add(component);
  }
  
  /**
  * Remove component from process watchers.
  */
  public void removeProcessWatcher(Component component)
  {
    processWatchers.remove(component);
  }
  
  /**
  * GUI Updater that enables and disables process watchers while Ogmios runs a process
  */
  public class OgmiosGUIUpdater implements Runnable
  {
    public boolean enable = false;
    public void run()
    {
      for (Component component : processWatchers)
      {
        component.setEnabled(enable);
      }
    }
  }

 /**
 * Invokes makeSettingsInterface and then setupComponentSettings
 */
 public static JMenu makeAndSetupComponentSettings(JComponent component, String key)
 {
   JMenu menu = makeSettingsInterface(component, key);
  setupComponentSettings(component);
  return menu;
 }

 /**
 * Parses and sets any settings for a given component
 */
 public static void setupComponentSettings(Component component)
 {
   String componentName = component.getName();
   String val, val1, val2;
    int num, num1, num2;
    if ((val = settingsMap.get(componentName + "BackColor")) != null)
    {
      num = OgmiosUtilities.tryParse(val);
      if (OgmiosUtilities.success)
        component.setBackground(new Color(num));
    }

    if ((val = settingsMap.get(componentName + "ForeColor")) != null)
    {
      num = OgmiosUtilities.tryParse(val);
      if (OgmiosUtilities.success)
        component.setForeground(new Color(num));
    }

    if ((val = settingsMap.get(componentName + "FontFamily")) != null)
    {
      if ((val1 = settingsMap.get(componentName + "FontStyle")) != null)
      {
        num1 = OgmiosUtilities.tryParse(val1);
        if (OgmiosUtilities.success)
          if ((val2 = settingsMap.get(componentName + "FontSize")) != null)
          {
            num2 = OgmiosUtilities.tryParse(val2);
            if (OgmiosUtilities.success)
              component.setFont(new Font(val, num1, num2));
          }
      }
    }
 }

 /**
 * Make a JMenu that provides an interface for changing a component's settings
 *
 * @param     component     The component to build the jmenu for
 * @param     uiKey     The UIKey to use for determining a component's defaults
 */
 public static JMenu makeSettingsInterface(final JComponent component, String uiKey)
 {
  String componentName = component.getName();
  JMenu settings = new JMenu(componentName + " Settings");
   if (component.isOpaque())
   {
   JMenuItem backColor = new JMenuItem("Back Color");
   settings.add(backColor);
   backColor.addActionListener(
    new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String componentName = component.getName();
        Color c;
        Color original;
        if ((c = JColorChooser.showDialog(null, "Set " + componentName + " Back Color", (original = component.getBackground()))) != null)
        {
          Component parent = component.getParent();
          if (parent instanceof JTabbedPane)
            ((JTabbedPane)parent).setSelectedComponent(component);
          component.setBackground(c);
          switch (JOptionPane.showConfirmDialog(null, "Would you like to save the " + componentName + "'s back color?", "Like what you see?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
          {
          case JOptionPane.YES_OPTION:
            settingsMap.put(componentName + "BackColor", Integer.toString(c.getRGB()));
            break;
          case JOptionPane.CANCEL_OPTION:
            component.setBackground(original);
          }
        }
      }
    }
    );
    }
   JMenuItem foreColor = new JMenuItem("Fore Color");
   settings.add(foreColor);
   JMenuItem font = new JMenuItem("Font");
   settings.add(font);
   JMenuItem defaults = new JMenuItem("Defaults");
   settings.add(defaults); 
    foreColor.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        String componentName = component.getName();
        Color c;
        Color original;
        if ((c = JColorChooser.showDialog(null, "Set " + componentName + " Fore Color", (original = component.getForeground()))) != null)
        {
          Component parent = component.getParent();
          if (parent instanceof JTabbedPane)
            ((JTabbedPane)parent).setSelectedComponent(component);
          component.setForeground(c);
          switch (JOptionPane.showConfirmDialog(null, "Would you like to save the " + componentName + "'s fore color?", "Like what you see?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
          {
          case JOptionPane.YES_OPTION:
            settingsMap.put(componentName + "ForeColor", Integer.toString(c.getRGB()));
            break;
          case JOptionPane.CANCEL_OPTION:
            component.setForeground(original);
          }
        }
      }
    }
    );

    font.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
         String componentName = component.getName();
        Font f;
        Font original;
        if ((f = FontDialog.showDialog(null, original = component.getFont(), "Set " + componentName + " Font")) != null)
        {
          Component parent = component.getParent();
          if (parent instanceof JTabbedPane)
            ((JTabbedPane)parent).setSelectedComponent(component);
          component.setFont(f);
          switch (JOptionPane.showConfirmDialog(null, "Would you like to save the " + componentName + "'s font?", "Like what you see?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
          {
          case JOptionPane.YES_OPTION:
            settingsMap.put(componentName + "FontFamily", f.getFamily());
            settingsMap.put(componentName + "FontSize", Integer.toString(f.getSize()));
            settingsMap.put(componentName + "FontStyle", Integer.toString(f.getStyle()));
            break;
          case JOptionPane.CANCEL_OPTION:
            component.setFont(original);
          }
        }
      }
    }
    );
    {
    final String key = uiKey;
    defaults.addActionListener(
      new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
       String componentName = component.getName();
        UIDefaults ud = UIManager.getDefaults();

        Color c = component.getBackground();
        Color newColor;
          Component parent = component.getParent();
          if (parent instanceof JTabbedPane)
            ((JTabbedPane)parent).setSelectedComponent(component);
        component.setBackground(newColor = (Color)ud.get(key + ".background"));
        switch (JOptionPane.showConfirmDialog(null, "Would you like to save the " + componentName + "'s back color?", "Like what you see?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
        {
        case JOptionPane.YES_OPTION:
          settingsMap.put(componentName + "BackColor", Integer.toString(newColor.getRGB()));
          break;
        case JOptionPane.CANCEL_OPTION:
          component.setBackground(c);
        }

        c = component.getForeground();
        component.setForeground(newColor = (Color)ud.get(key + ".foreground"));
        switch (JOptionPane.showConfirmDialog(null, "Would you like to save the " + componentName + "'s fore color?", "Like what you see?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
        {
        case JOptionPane.YES_OPTION:
          settingsMap.put(componentName + "ForeColor", Integer.toString(newColor.getRGB()));
          break;
        case JOptionPane.CANCEL_OPTION:
          component.setForeground(c);
        }


        Font f = component.getFont();
        Font newFont;
        component.setFont(newFont = (Font)ud.get(key + ".font"));
        switch (JOptionPane.showConfirmDialog(null, "Would you like to save the " + componentName + "'s font?", "Like what you see?", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
        {
        case JOptionPane.YES_OPTION:
          settingsMap.put(componentName + "FontFamily", newFont.getFamily());
          settingsMap.put(componentName + "FontSize", Integer.toString(newFont.getSize()));
          settingsMap.put(componentName + "FontStyle", Integer.toString(newFont.getStyle()));
          break;
        case JOptionPane.CANCEL_OPTION:
          component.setFont(f);
        }

      }
    }
    );
   }
  return settings;
 }

  /**
  * Save Ogmios' settings.
  */
  public void saveSettings()
  {

    Set<String> set = settingsMap.keySet();
    if (set.size() > 0)
    {
      try
      {
        BufferedWriter writer = new BufferedWriter(new FileWriter("settings.ogs"));
        Iterator<String> i = set.iterator();
        String newLine = System.getProperty("line.separator");
        while (true)
        {
          String toWrite = i.next();
          toWrite += ":" + settingsMap.get(toWrite);
          if (i.hasNext())
            writer.write(toWrite + newLine);
          else
          {
            writer.write(toWrite);
            break;
          }

        }
        writer.close();
      }
      catch (Throwable ex)
      {
      }
    }

  }

  /**
  * A RadioButtonMenuItem that encapsulates a pattern and the group number that
  * contains the important info to parse.
  */
  public static class RegexRadioButtonMenuItem extends JRadioButtonMenuItem
  {
    public final Pattern pattern;
    public final int group;
    public RegexRadioButtonMenuItem(String regex, int group)
    {
      super(regex);
      pattern = Pattern.compile(regex);
      this.group = group;
    }
  }

  /**
  * A RadioButtonMenuItem that encapsulates the name of a Swing look and feel.
  */
  public static class LAFRadioButtonMenuItem extends JRadioButtonMenuItem
  {
    public final String lookAndFeel;
    public LAFRadioButtonMenuItem(String laf, String shortName)
    {
      lookAndFeel = laf;
      setText(shortName);
    }
  }

  /**
  * Tries to convert the current untitled document to an OgmiosNode.
  */
  public boolean saveCurrentDocumentToNode(String title)
  {
     JFileChooser fileDialog = OgmiosFileChooser.getFileDialog(".java | 'Java Files'");

        fileDialog.setDialogTitle(title);
        if (fileDialog.showSaveDialog(Ogmios.this) == JFileChooser.APPROVE_OPTION)
        {
          try
          {
            File javaFile;
            FileWriter writer = new FileWriter(javaFile = fileDialog.getSelectedFile() );
            fileDialog.setSelectedFile(null);
            writer.write(code.getText());
            writer.close();
            //OgmiosUtilities.clearFileDialog();
            undo.setLimit(100);
            undo.discardAllEdits();
            undo.setLimit(MAX_UNDO_LEVEL);

            OgmiosNode node;
            treeModel.insertNodeInto(node = new OgmiosNode(javaFile.getCanonicalPath()), treeRoot, treeRoot.getChildCount());
            node.document = code.getDocument();
            node.verticalPosition = (codeScroll.getVerticalScrollBar()).getValue();
            node.horizontalPosition = (codeScroll.getHorizontalScrollBar()).getValue();
            activeNode = node;
            codeTab.setSelectedComponent(true);

            tree.scrollPathToVisible(new TreePath(node.getPath()));
            tree.repaint();
            node.setDefaultDocumentListener(createDefaultDocumentListener(node), true);
            node.setUndo(true);
           return true;
          }

          catch (IOException ex)
          {
            OgmiosUtilities.showErrorBox(Ogmios.this, ex, "IO:Saving Error");
          }
       }
    return false;
 }


  /**
  * Ask the user whether they want to save the current untitled document.
  */
  public boolean promptUntitledWorkSave()
  {
    if (activeNode == null && code.getText().length() > 0)
      switch (JOptionPane.showConfirmDialog(Ogmios.this, "Do you want to save your untitled work?", "Untitled Work", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE))
      {
      case JOptionPane.YES_OPTION:
        return saveCurrentDocumentToNode("Save Untitled File");
      case JOptionPane.NO_OPTION:
        break;
      default:
        return false;
      }
    return true;

  }

 public Munchkin getMunchkin()
 {
  if (munchkin == null)
  {
    munchkin = new Munchkin(Ogmios.this);
    munchkin.registerMunch(new ExtensionMunch());
    munchkin.registerMunch(new CommandMunch());
    String val;
    if ((val = settingsMap.get("mkHeight")) != null)
    {
      int height;
      height  = OgmiosUtilities.tryParse(val);
      if (OgmiosUtilities.success)
        if ((val = settingsMap.get("mkWidth")) != null)
        {
          int width;
          width = OgmiosUtilities.tryParse(val);
          if (OgmiosUtilities.success)
          {
            munchkin.setSize(width, height);
          }
        }
    }
    munchkin.addComponentListener(
      new ComponentAdapter()
    {
      public void componentResized(ComponentEvent e)
      {
        settingsMap.put("mkWidth", Integer.toString(ogmiosGUI.munchkin.getWidth()));
        settingsMap.put("mkHeight", Integer.toString(ogmiosGUI.munchkin.getHeight()));
      }
    }
    );

  }
  return munchkin;
 }

 public ArchiveBuilder getArchiveBuilder()
 {
   if (archiveBuilder == null)
   {
    archiveBuilder = new ArchiveBuilder(Ogmios.this);
    archiveBuilder.registerArchiver(new ogmios.components.archivers.ZipArchiver());
    archiveBuilder.registerArchiver(new ogmios.components.archivers.JarArchiver());
   }
   return archiveBuilder;
 }

 public static Set<String> getMunchBlackList()
 {
   if (munchBlacklist == null)
   {
     munchBlacklist = new HashSet<String>();
    munchBlacklist.add("commands");
    munchBlacklist.add("extensions");
   }
    return munchBlacklist;
 }

 public static ClassLoader getMunchLoader()
 {
  if (munchLoader == null)
  {
   try
   {
    munchLoader =new URLClassLoader(new URL[]{new File(System.getProperty("user.dir")).toURI().toURL()});
   }
    catch(MalformedURLException ex)
   {
    munchLoader = Ogmios.class.getClassLoader();
   }
  }
  return munchLoader;
 }

 public TemplateManager getJavaTemplateManager()
 {
  if (javaTemplateManager == null)
  {
   javaTemplateManager = new TemplateManager("templates" + File.separator + "java", Ogmios.this);
   String val = settingsMap.get("Close Java Template Manager After Creation");
   if (val != null)
   {
    boolean b = OgmiosUtilities.tryParseBooleanNumber(val);
    if (OgmiosUtilities.success)
    {
     javaTemplateManager.setCloseAfterCreation(b);
    }
   }
   javaTemplateManager.getCloseAfterCreationCheckBox().addItemListener(
    new ItemListener()
    {
     public void itemStateChanged(ItemEvent e)
     {
      settingsMap.put("Close Java Template Manager After Creation", OgmiosUtilities.booleanNumberString(javaTemplateManager.getCloseAfterCreation()));
     }
    }
    );
  }
  return javaTemplateManager;
 }
 
 /**
 * Ogmios will try to do something with the contents of the MunchCapsule.
 */
 public void tryToLoad(MunchCapsule munchCapsule)
 {

   Munch munch = munchCapsule.munch;
   if (munch instanceof ExtensionMunch)
   {
    try
    {
     ClassLoader loader =new NoCacheClassLoader(new URLClassLoader(new URL[]{new File(System.getProperty("user.dir")).toURI().toURL()}), getMunchBlackList());//Ogmios.class.getClassLoader();
     String name = munchCapsule.fileName;
     Object newExtension = (loader.loadClass("extensions." + name)).newInstance();

     if (newExtension instanceof Extension)
     {
       Set<String> classNames = extensions.keySet();
       for (Iterator<String> iterator = classNames.iterator(); iterator.hasNext();)
       {
         if (iterator.next().equals(name))
        {
         extensions.get(name).clean();
         iterator.remove();
         break;
        }
       }
      Extension extension = (Extension)newExtension;
      extension.initialize();
      ogmiosGUI.extensions.put(name, extension);       
     }
    }
    catch(Throwable ex)
    {
      OgmiosUtilities.showErrorBox(Ogmios.this, ex, "Class:Load Error"); 
    }
   }
   else if (munch instanceof CommandMunch)
    {
      CommandManager.putNew(munchCapsule.fileName);
    }
 }
 

}
